/********************************************************************************
* Copyright (c) 2009, Matteo Pelati (matteo.pelati@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of the <organization> nor the
*       names of its contributors may be used to endorse or promote products
*       derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Matteo Pelati ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**************************************************************************************/

#pragma once


#include <fstream>
#include <string>
#include <cstdlib>
#include <stdlib.h>
#include <stdio.h>
#include <vcclr.h>
#include "dbxml/DbXml.hpp"
#include "dbXmlLib.h"
#include "DbException.h"
#include "DbXmlException.h"
#include "DbXmlTransaction.h"
#include "DbXmlQueryContext.h"

using namespace DbXml;
using namespace System;
using namespace System::Collections::Generic;
using namespace std;

typedef ::System::Collections::IEnumerable IUntypedEnumerable;
typedef ::System::Collections::IEnumerator IUntypedEnumerator;
typedef ::System::Collections::ICollection IUntypedCollection;

namespace BerkeleyDB { namespace Xml
{
	ref class DbXmlValue;
	ref class DbXmlDocument;

	public ref class DbXmlResults : DbGenericObject, public IDbXmlDatabaseItem
	{
	private:
		XmlResults* n_res;
		DbXmlTransaction^ currTxn;
		DbXmlQueryContext^ currCtx;
	internal:
		XmlResults* GetInnerObject()
		{
			return n_res;
		}
		/*
		DbXmlResults(DbGenericObject^ parent, XmlResults* res, DbXmlTransaction^ txn, DbXmlQueryContext^ ctx) : DbGenericObject(parent)
		{
			n_res = res;
			currTxn = txn;
			currCtx = ctx;
		}
		*/
		DbXmlResults(DbGenericObject^ parent, XmlResults& res, DbXmlTransaction^ txn, DbXmlQueryContext^ ctx) : DbGenericObject(parent)
		{
			n_res = new XmlResults(res);
			currTxn = txn;
			currCtx = ctx;
		}
	public:
		~DbXmlResults()
		{
			GC::SuppressFinalize(this);
			this->!DbXmlResults();
		}
		!DbXmlResults()
		{
			delete n_res;
		}
	public:

		virtual DbXmlDatabaseItemType GetDatabaseItemType()
		{
			return DbXmlDatabaseItemType::UnknownSet;
		}

		PROPERTY_RET_ENUM_GET(EvaluationType,, EvaluationType, DbXmlQueryEvalType, XmlQueryContext::EvaluationType);

		virtual void Add(DbXmlValue^ value);
		virtual bool HasNext();
		virtual bool HasPrevious();
		virtual bool Next(DbXmlValue^% value);
		virtual bool Next(DbXmlDocument^% doc);
		virtual bool Peek(DbXmlValue^% value);
		virtual bool Peek(DbXmlDocument^% doc);
		virtual bool Previous(DbXmlValue^% value);
		virtual bool Previous(DbXmlDocument^% doc);
		virtual void Reset();
		virtual size_t Size();
	};


	public ref class DbXmlValueCollection : 
		DbXmlResults, IEnumerable<DbXmlValue^>, IEnumerator<DbXmlValue^>
	{
	private:
		DbXmlValue^ currVal;
	public:
		/*
		DbXmlValueCollection(DbGenericObject^ parent, XmlResults* res, DbXmlTransaction^ txn, DbXmlQueryContext^ ctx) : DbXmlResults(parent, res, txn, ctx) 
		{
			currVal = nullptr;
		}
		*/
		
		DbXmlValueCollection(DbGenericObject^ parent, XmlResults& res, DbXmlTransaction^ txn, DbXmlQueryContext^ ctx) : DbXmlResults(parent, res, txn, ctx) 
		{
			currVal = nullptr;
		}

		virtual DbXmlDatabaseItemType GetDatabaseItemType() override
		{
			return DbXmlDatabaseItemType::XmlNodeSet;
		}

		virtual IEnumerator<DbXmlValue^>^ GetTypedEnumerator() = IEnumerable<DbXmlValue^>::GetEnumerator
		{
			return (IEnumerator<DbXmlValue^>^) this;
		}

		virtual IUntypedEnumerator^ GetUntypedEnumerator() = IUntypedEnumerable::GetEnumerator
		{
			return (IUntypedEnumerator^) this;
		}

		virtual bool MoveNext()
		{
			return this->Next(currVal);
		}

		property DbXmlValue^ Current 
		{
			virtual DbXmlValue^ get() = IEnumerator<DbXmlValue^>::Current::get
			{
				return currVal;
			}
		}

		property Object^ CurrentUntyped 
		{
			virtual Object^ get () = IUntypedEnumerator::Current::get
			{
				return currVal;
			}
		}
	};


	
	public ref class DbXmlDocumentCollection : 
		DbXmlResults, IEnumerable<DbXmlDocument^>, IEnumerator<DbXmlDocument^>
	{
	private:
		DbXmlDocument^ currDoc;
	public:
		/*
		DbXmlDocumentCollection(DbGenericObject^ parent, XmlResults* res, DbXmlTransaction^ txn, DbXmlQueryContext^ ctx) : DbXmlResults(parent, res, txn, ctx) 
		{
			currDoc = nullptr;
		}
		*/
		
		DbXmlDocumentCollection(DbGenericObject^ parent, XmlResults& res, DbXmlTransaction^ txn, DbXmlQueryContext^ ctx) : DbXmlResults(parent, res, txn, ctx) 
		{
			currDoc = nullptr;
		}

		virtual DbXmlDatabaseItemType GetDatabaseItemType() override
		{
			return DbXmlDatabaseItemType::DocumentSet;
		}

		virtual IEnumerator<DbXmlDocument^>^ GetTypedEnumerator() = IEnumerable<DbXmlDocument^>::GetEnumerator
		{
			return (IEnumerator<DbXmlDocument^>^) this;
		}

		virtual IUntypedEnumerator^ GetUntypedEnumerator() = IUntypedEnumerable::GetEnumerator
		{
			return (IUntypedEnumerator^) this;
		}

		virtual bool MoveNext()
		{
			return this->Next(currDoc);
		}

		property DbXmlDocument^ Current 
		{
			virtual DbXmlDocument^ get() = IEnumerator<DbXmlDocument^>::Current::get
			{
				return currDoc;
			}
		}

		property Object^ CurrentUntyped 
		{
			virtual Object^ get () = IUntypedEnumerator::Current::get
			{
				return (Object^) currDoc;
			}
		}
	};




	
}}


